home *** CD-ROM | disk | FTP | other *** search
/ BCI NET 2 / BCI NET 2.iso / archives / programming / languages / editpat.lha / EditPat.Mod (.txt) < prev    next >
Encoding:
Oberon Text  |  1994-12-02  |  33.0 KB  |  1,305 lines

  1. Syntax10.Scn.Fnt
  2. Syntax10b.Scn.Fnt
  3. FoldElems
  4. MODULE EditPat; (* V0.6 (C) 4 Nov 94 by Ralf Degner *)
  5.     IMPORT
  6.         Display, DisplayPat, Viewers, Oberon, Input, MenuViewers, TextFrames, Texts, Files, Fonts, Out;
  7.     CONST
  8.         Menu = "System.Close  System.Copy  System.Grow  EditPat.Draw  EditPat.Fill  EditPat.Insert  EditPat.Store ";
  9.         ObenOffset=25;SeitenOffset=10;
  10.         OO=ObenOffset;SO=SeitenOffset;
  11.         MaxKasten=50;
  12.         DrawMode=1; FillMode=2; InsertMode=3;
  13.         MaxColors=256;MaxAuf=2048;
  14.     TYPE
  15.         SetArrayType = POINTER TO ARRAY OF SET;
  16.         FeldType = POINTER TO ARRAY OF ARRAY OF INTEGER;
  17.         PatData = POINTER TO PatDataDesc;
  18.         PatDataDesc = RECORD
  19.             NextData: PatData;
  20.             Color: INTEGER;
  21.             SetData: SetArrayType;
  22.         END;
  23.         Pat = POINTER TO PatDesc;
  24.         PatDesc = RECORD(PatDataDesc)
  25.             Next, Last: Pat;
  26.             W, H: INTEGER;
  27.         END;
  28.         Data = POINTER TO DataDesc;
  29.         DataDesc = RECORD
  30.             ActivPat, LastKilled: Pat;
  31.             XAuf, YAuf: INTEGER;
  32.             Color, DrawMode: INTEGER;
  33.             Feld: FeldType;
  34.             Undo: FeldType;
  35.             Name: ARRAY 128 OF CHAR;
  36.             Marked: BOOLEAN;
  37.             MText: Texts.Text;
  38.         END;
  39.         Frame = POINTER TO FrameDesc;
  40.         FrameDesc = RECORD(Display.FrameDesc)
  41.             d: Data;
  42.             KG: INTEGER;
  43.             LastModMsg: BOOLEAN;
  44.             Grid, GridType: BOOLEAN;
  45.         END;
  46.         EditPatMsg = RECORD(Display.FrameMsg)
  47.             d: Data;
  48.         END;
  49.         PlotAllMsg = RECORD(EditPatMsg)
  50.         END;
  51.         PlotKastenMsg = RECORD(EditPatMsg)
  52.             X, Y: INTEGER;
  53.         END;
  54.         DrawModeMsg = RECORD(EditPatMsg)
  55.         END;
  56.         Clip: POINTER TO ARRAY OF ARRAY OF INTEGER;
  57.         ClipW, ClipH: INTEGER;
  58.         W: Texts.Writer;
  59.         F: Fonts.Font;
  60.     (* set ! to menu of frame *)
  61.     PROCEDURE MarkData(f: Frame);
  62.     BEGIN
  63.         IF ~f.d.Marked THEN
  64.             f.d.Marked:=TRUE;
  65.             Texts.Write(W, "!");
  66.             Texts.Append(f.d.MText, W.buf);
  67.         END;
  68.     END MarkData;
  69.     (* clear edit-field *)
  70.     PROCEDURE ClearFeld(d: Data; Color: INTEGER);
  71.         VAR
  72.             DumX, DumY: INTEGER;
  73.     BEGIN
  74.         FOR DumX:=0 TO d.XAuf-1 DO
  75.             FOR DumY:=0 TO d.YAuf-1 DO
  76.                 d.Feld[DumX, DumY]:=Color;
  77.             END;
  78.         END;
  79.     END ClearFeld;
  80.     (* insert new pattern *)
  81.     PROCEDURE NewPat(d: Data; W, H: INTEGER);
  82.         VAR NPat: Pat;
  83.     BEGIN
  84.         NEW(NPat);
  85.         NPat.W:=W;NPat.H:=H;
  86.         NPat.NextData:=NIL;
  87.         IF d.ActivPat=NIL THEN
  88.             NPat.Next:=NIL;
  89.             NPat.Last:=NIL;
  90.         ELSE;
  91.             IF d.ActivPat.Next#NIL THEN
  92.                 d.ActivPat.Next.Last:=NPat;
  93.             END;
  94.             NPat.Next:=d.ActivPat.Next;
  95.             NPat.Last:=d.ActivPat;
  96.             d.ActivPat.Next:=NPat;
  97.         END;
  98.         d.ActivPat:=NPat;
  99.     END NewPat;
  100.     (* search first pattern *)
  101.     PROCEDURE FirstPat(FirstPat: Pat): Pat;
  102.     BEGIN
  103.         IF FirstPat=NIL THEN RETURN NIL;END;
  104.         WHILE FirstPat.Last#NIL DO
  105.             FirstPat:=FirstPat.Last;
  106.         END;
  107.         RETURN FirstPat;
  108.     END FirstPat;
  109.     (* search the last pattern *)
  110.     PROCEDURE TheLastPat(LastPat: Pat): Pat;
  111.     BEGIN
  112.         IF LastPat=NIL THEN RETURN NIL;END;
  113.         WHILE LastPat.Next#NIL DO
  114.             LastPat:=LastPat.Next;
  115.         END;
  116.         RETURN LastPat;
  117.     END TheLastPat;
  118.     (* count number of patterns *)
  119.     PROCEDURE CountPat(APat: Pat): LONGINT;
  120.         VAR Anz: LONGINT;
  121.     BEGIN
  122.         Anz:=0;
  123.         WHILE APat#NIL DO
  124.             INC(Anz);
  125.             APat:=APat.Next;
  126.         END;
  127.         RETURN Anz;
  128.     END CountPat;
  129.     (* Get Number of ActivPat *)
  130.     PROCEDURE GetNumber(NPat: Pat): LONGINT;
  131.         VAR Anz: LONGINT;
  132.     BEGIN
  133.         Anz:=0;
  134.         WHILE NPat.Last#NIL DO
  135.             INC(Anz);
  136.             NPat:=NPat.Last;
  137.         END;
  138.         RETURN Anz;
  139.     END GetNumber;
  140.     (* store one Display.Pattern to memory *)
  141.     PROCEDURE OnePatToMem(d: Data; Color: INTEGER; LastData: PatData; XPos: INTEGER): PatData;
  142.         VAR
  143.             NewData: PatData;
  144.             SetData: SetArrayType;
  145.             DumX, DumY: INTEGER;
  146.             OneSet: SET;
  147.     BEGIN
  148.         NEW(NewData);
  149.         NewData.NextData:=NIL;
  150.         LastData.NextData:=NewData;
  151.         NEW(SetData, d.YAuf);
  152.         NewData.SetData:=SetData;
  153.         NewData.Color:=Color;
  154.         FOR DumY:=0 TO d.YAuf-1 DO
  155.             OneSet:={};
  156.             DumX:=0;
  157.             REPEAT
  158.                 IF d.Feld[DumX+XPos, DumY]=Color THEN
  159.                     INCL(OneSet, DumX);
  160.                 END;
  161.                 INC(DumX);
  162.             UNTIL (DumX=32) OR (DumX+XPos=d.XAuf);
  163.             SetData^[DumY]:=OneSet;
  164.         END;
  165.         RETURN NewData;
  166.     END OnePatToMem;
  167.     (* store pattern from display to memory *)
  168.     PROCEDURE StoreToMem(d: Data);
  169.         VAR
  170.             ColorMap: ARRAY MaxColors OF BOOLEAN;
  171.             LastData: PatData;
  172.             DumX, DumY: INTEGER;
  173.     BEGIN
  174.         IF d.ActivPat=NIL THEN RETURN;END;
  175.         FOR DumX:=0 TO MaxColors-1 DO
  176.             ColorMap[DumX]:=FALSE;
  177.         END;
  178.         FOR DumX:=0 TO d.XAuf-1 DO
  179.             FOR DumY:=0 TO d.YAuf-1 DO
  180.                 ColorMap[d.Feld[DumX, DumY]]:=TRUE;
  181.             END;
  182.         END;
  183.         LastData:=d.ActivPat;
  184.         FOR DumX:=1 TO MaxColors-1 DO
  185.             IF ColorMap[DumX] THEN
  186.                 DumY:=0;
  187.                 REPEAT
  188.                     LastData:=OnePatToMem(d, DumX, LastData, DumY);
  189.                     INC(DumY, 32);
  190.                 UNTIL DumY>d.XAuf;
  191.             END;
  192.         END;
  193.         LastData.NextData:=NIL;
  194.     END StoreToMem;
  195.     (* put pattern from memory to field *)
  196.     PROCEDURE PatToFeld(d: Data);
  197.         VAR
  198.             DumX, DumY, Count, Color: INTEGER;
  199.             NewFeld: FeldType;
  200.             UsedPData: PatData;
  201.             OneSet: SET;
  202.     BEGIN
  203.         IF d.ActivPat=NIL THEN RETURN;END;
  204.         d.XAuf:=d.ActivPat.W;
  205.         d.YAuf:=d.ActivPat.H;
  206.         NEW(NewFeld, d.XAuf, d.YAuf);
  207.         d.Feld:=NewFeld;
  208.         ClearFeld(d, Display.black);
  209.         UsedPData:=d.ActivPat;
  210.         Color:=Display.black;
  211.         WHILE (UsedPData.NextData#NIL) DO
  212.             UsedPData:=UsedPData.NextData;
  213.             IF UsedPData.Color#Color THEN
  214.                 Color:=UsedPData.Color;
  215.                 Count:=0;
  216.             END;
  217.             FOR DumY:=0 TO d.YAuf-1 DO
  218.                 OneSet:=UsedPData.SetData[DumY];
  219.                 FOR DumX:=0 TO 31 DO
  220.                     IF DumX IN OneSet THEN
  221.                         NewFeld[DumX+Count, DumY]:=Color;
  222.                     END;
  223.                 END;
  224.             END;
  225.             INC(Count, 32);
  226.         END;
  227.     END PatToFeld;
  228.     (* get selected frame *)    
  229.     PROCEDURE GetFrame(VAR f: Display.Frame): BOOLEAN;
  230.         VAR v: Viewers.Viewer;
  231.     BEGIN
  232.         IF Oberon.Par.frame=Oberon.Par.vwr.dsc THEN
  233.             IF (Oberon.Par.frame # NIL) THEN
  234.                 f:=Oberon.Par.frame.next;
  235.                 RETURN TRUE;
  236.             END;
  237.         ELSE
  238.             v:=Oberon.MarkedViewer();
  239.             IF (v.dsc # NIL) & (v.dsc.next # NIL) THEN
  240.                 f:=v.dsc.next;
  241.                 RETURN TRUE;
  242.             END
  243.         END;
  244.         RETURN FALSE;
  245.     END GetFrame;
  246.     (* get parameters from Menu, Text or Selection *)
  247.     PROCEDURE GetPar(VAR S: Texts.Scanner): BOOLEAN;
  248.         VAR
  249.             text: Texts.Text;
  250.             beg, end, time: LONGINT;
  251.     BEGIN
  252.         Texts.OpenScanner(S, Oberon.Par.text, Oberon.Par.pos);
  253.         Texts.Scan(S);
  254.         IF S.class=Texts.Char THEN
  255.             IF S.c="^" THEN
  256.                 Oberon.GetSelection(text, beg, end, time);
  257.                 IF time=-1 THEN RETURN FALSE; END;
  258.                 Texts.OpenScanner(S, text, beg);
  259.                 Texts.Scan(S);
  260.             END;
  261.         END;
  262.         RETURN TRUE;
  263.     END GetPar;
  264.     (* changes the drawing color *)
  265.     PROCEDURE ChangeColor*;
  266.         VAR
  267.             S: Texts.Scanner;
  268.             f, g: Display.Frame;
  269.     BEGIN
  270.         IF GetFrame(g) THEN
  271.             f:=g;
  272.             WITH f: Frame DO
  273.                 IF GetPar(S) THEN
  274.                     IF S.class=Texts.Int THEN
  275.                         IF (S.i>=0) & (S.i<MaxColors) THEN
  276.                             f.d.Color:=SHORT(S.i);
  277.                         END;
  278.                     END;
  279.                 END;
  280.             ELSE
  281.             END;
  282.         END;
  283.     END ChangeColor;
  284.     (* changes mode to DRAW *)
  285.     PROCEDURE Draw*;
  286.         VAR
  287.             S: Texts.Scanner;
  288.             f, g: Display.Frame;
  289.             dmmsg: DrawModeMsg;
  290.     BEGIN
  291.         IF GetFrame(g) THEN
  292.             f:=g;
  293.             WITH f: Frame DO
  294.                 IF f.d.DrawMode#DrawMode THEN
  295.                     f.d.DrawMode:=DrawMode;
  296.                     dmmsg.d:=f.d;
  297.                     Viewers.Broadcast(dmmsg);
  298.                 END;
  299.             ELSE
  300.             END;
  301.         END;
  302.     END Draw;
  303.     (* changes mode to FILL *)
  304.     PROCEDURE Fill*;
  305.         VAR
  306.             S: Texts.Scanner;
  307.             f, g: Display.Frame;
  308.             dmmsg: DrawModeMsg;
  309.     BEGIN
  310.         IF GetFrame(g) THEN
  311.             f:=g;
  312.             WITH f: Frame DO
  313.                 IF f.d.DrawMode#FillMode THEN
  314.                     f.d.DrawMode:=FillMode;
  315.                     dmmsg.d:=f.d;
  316.                     Viewers.Broadcast(dmmsg);
  317.                 END;
  318.             ELSE
  319.             END;
  320.         END;
  321.     END Fill;
  322.     (* changes mode to INSERT *)
  323.     PROCEDURE Insert*;
  324.         VAR
  325.             S: Texts.Scanner;
  326.             f, g: Display.Frame;
  327.             dmmsg: DrawModeMsg;
  328.     BEGIN
  329.         IF GetFrame(g) THEN
  330.             f:=g;
  331.             WITH f: Frame DO
  332.                 IF f.d.DrawMode#InsertMode THEN
  333.                     f.d.DrawMode:=InsertMode;
  334.                     dmmsg.d:=f.d;
  335.                     Viewers.Broadcast(dmmsg);
  336.                 END;
  337.             ELSE
  338.             END;
  339.         END;
  340.     END Insert;
  341.     (* show previous Pat *)
  342.     PROCEDURE Prev*;
  343.         VAR
  344.             pamsg: PlotAllMsg;
  345.             f, g: Display.Frame;
  346.     BEGIN
  347.         IF GetFrame(g) THEN
  348.             f:=g;
  349.             WITH f: Frame DO
  350.                 IF f.d.ActivPat#NIL THEN
  351.                     IF f.d.ActivPat.Last#NIL THEN
  352.                         pamsg.d:=f.d;
  353.                         StoreToMem(f.d);
  354.                         f.d.ActivPat:=f.d.ActivPat.Last;
  355.                         PatToFeld(f.d);
  356.                         Viewers.Broadcast(pamsg);
  357.                     END;
  358.                 END;
  359.             ELSE
  360.             END;
  361.         END;
  362.     END Prev;
  363.     (* show next Pat *)
  364.     PROCEDURE Next*;
  365.         VAR
  366.             pamsg: PlotAllMsg;
  367.             f, g: Display.Frame;
  368.     BEGIN
  369.         IF GetFrame(g) THEN
  370.             f:=g;
  371.             WITH f: Frame DO
  372.                 IF f.d.ActivPat#NIL THEN
  373.                     IF f.d.ActivPat.Next#NIL THEN
  374.                         pamsg.d:=f.d;
  375.                         StoreToMem(f.d);
  376.                         f.d.ActivPat:=f.d.ActivPat.Next;
  377.                         PatToFeld(f.d);
  378.                         Viewers.Broadcast(pamsg);
  379.                     END;
  380.                 END;
  381.             ELSE
  382.             END;
  383.         END;
  384.     END Next;
  385.     (* show first pat *)
  386.     PROCEDURE First*;
  387.         VAR
  388.             pamsg: PlotAllMsg;
  389.             f, g: Display.Frame;
  390.     BEGIN
  391.         IF GetFrame(g) THEN
  392.             f:=g;
  393.             WITH f: Frame DO
  394.                 IF f.d.ActivPat#NIL THEN
  395.                     IF f.d.ActivPat.Last#NIL THEN
  396.                         pamsg.d:=f.d;
  397.                         StoreToMem(f.d);
  398.                         f.d.ActivPat:=FirstPat(f.d.ActivPat);
  399.                         PatToFeld(f.d);
  400.                         Viewers.Broadcast(pamsg);
  401.                     END;
  402.                 END;
  403.             ELSE
  404.             END;
  405.         END;
  406.     END First;
  407.     (* show the last pat *)
  408.     PROCEDURE Last*;
  409.         VAR
  410.             pamsg: PlotAllMsg;
  411.             f, g: Display.Frame;
  412.     BEGIN
  413.         IF GetFrame(g) THEN
  414.             f:=g;
  415.             WITH f: Frame DO
  416.                 IF f.d.ActivPat#NIL THEN
  417.                     IF f.d.ActivPat.Next#NIL THEN
  418.                         pamsg.d:=f.d;
  419.                         StoreToMem(f.d);
  420.                         f.d.ActivPat:=TheLastPat(f.d.ActivPat);
  421.                         PatToFeld(f.d);
  422.                         Viewers.Broadcast(pamsg);
  423.                     END;
  424.                 END;
  425.             ELSE
  426.             END;
  427.         END;
  428.     END Last;
  429.     (* zoom in or out *)
  430.     PROCEDURE Goto*;
  431.         VAR
  432.             pamsg: PlotAllMsg;
  433.             S: Texts.Scanner;
  434.             f, g: Display.Frame;
  435.             Dummy: LONGINT;
  436.     BEGIN
  437.         IF GetFrame(g) THEN
  438.             f:=g;
  439.             WITH f: Frame DO
  440.                 IF GetPar(S) THEN
  441.                     IF S.class=Texts.Int THEN
  442.                         Dummy:=CountPat(f.d.ActivPat);
  443.                         IF (S.i>=0) & (S.i<Dummy) THEN
  444.                             Dummy:=S.i;
  445.                             pamsg.d:=f.d;
  446.                             StoreToMem(f.d);
  447.                             f.d.ActivPat:=FirstPat(f.d.ActivPat);
  448.                             WHILE Dummy#0 DO
  449.                                 DEC(Dummy);
  450.                                 f.d.ActivPat:=f.d.ActivPat.Next;
  451.                             END;
  452.                             PatToFeld(f.d);
  453.                             Viewers.Broadcast(pamsg);                            
  454.                         END;
  455.                     END;
  456.                 END;
  457.             ELSE
  458.             END;
  459.         END;
  460.     END Goto;
  461.     (* zoom in or out *)
  462.     PROCEDURE Zoom*;
  463.         VAR
  464.             pamsg: PlotAllMsg;
  465.             S: Texts.Scanner;
  466.             f, g: Display.Frame;
  467.     BEGIN
  468.         IF GetFrame(g) THEN
  469.             f:=g;
  470.             WITH f: Frame DO
  471.                 IF GetPar(S) THEN
  472.                     pamsg.d:=f.d;
  473.                     IF S.class=Texts.Char THEN
  474.                         IF S.c="+" THEN
  475.                             IF f.KG<MaxKasten THEN
  476.                                 INC(f.KG);
  477.                                 f.handle(f, pamsg);
  478.                             END;
  479.                         ELSIF S.c="-" THEN
  480.                             IF f.KG>1 THEN
  481.                                 DEC(f.KG);
  482.                                 f.handle(f, pamsg);
  483.                             END;
  484.                         END;
  485.                     ELSIF S.class=Texts.Int THEN
  486.                         IF (S.i>0) & (S.i<=MaxKasten) THEN
  487.                             f.KG:=SHORT(S.i);
  488.                             f.handle(f, pamsg);
  489.                         END;
  490.                     END;
  491.                 END;
  492.             ELSE
  493.             END;
  494.         END;
  495.     END Zoom;
  496.     (* pattern coordinates to frame coordinates *)
  497.     PROCEDURE KastenToFrame(f: Frame; XK, YK: INTEGER; VAR XF, YF: INTEGER);
  498.         VAR XWert, YWert, Dum: INTEGER;
  499.     BEGIN
  500.         IF f.Grid THEN
  501.             XWert:=1;
  502.         ELSE
  503.             XWert:=0;
  504.         END;
  505.         Dum:=f.KG+XWert;
  506.         XWert:=f.X+SeitenOffset+XWert;
  507.         YWert:=f.Y+f.H-ObenOffset-f.d.YAuf*Dum;
  508.         XF:=XWert+XK*Dum;
  509.         YF:=YWert+YK*Dum;
  510.     END KastenToFrame;
  511.     (* frame coordinates to pattern coordinates *)
  512.     PROCEDURE FrameToKasten(f: Frame; XF, YF: INTEGER; VAR XK, YK: INTEGER): BOOLEAN;
  513.         VAR Dum, DumX, DumY: INTEGER;
  514.     BEGIN
  515.         IF f.Grid THEN
  516.             Dum:=f.KG+1;
  517.         ELSE
  518.             Dum:=f.KG;
  519.         END;
  520.         DumX:=(XF-SO-f.X);
  521.         DumY:=(YF+OO+f.d.YAuf*Dum-f.H-f.Y);
  522.         IF f.Grid THEN
  523.             IF ((DumX MOD Dum)=0) OR ((DumY MOD Dum)=0) THEN RETURN FALSE;END;
  524.             XK:=DumX DIV Dum;YK:=DumY DIV Dum;
  525.         ELSE
  526.             XK:=DumX DIV f.KG;YK:=DumY DIV f.KG;
  527.         END;
  528.         IF (XK<0) OR (YK<0) OR (XK>=f.d.XAuf) OR (YK>=f.d.YAuf) THEN RETURN FALSE;END;
  529.         RETURN TRUE;
  530.     END FrameToKasten;
  531.     (* plot whole field at frame *)
  532.     PROCEDURE PlotFeld(f: Frame);
  533.         VAR
  534.             DX, DY, Dum: INTEGER;
  535.             XWert, YWert: INTEGER;
  536.     BEGIN
  537.         IF f.Grid THEN
  538.             XWert:=1;
  539.         ELSE
  540.             XWert:=0;
  541.         END;
  542.         Dum:=f.KG+XWert;
  543.         DX:=(Dum)*f.d.XAuf+2-XWert;
  544.         DY:=(Dum)*f.d.YAuf+2-XWert;
  545.         IF f.GridType THEN
  546.             Display.ReplConstC(f, Display.white, f.X+SO-1+XWert, f.Y+f.H-OO-DY+1-XWert, DX, DY, Display.replace);
  547.         ELSE
  548.             Display.ReplPatternC(f, Display.white, Display.grey1, f.X+SO-1+XWert, f.Y+f.H-OO-DY+1-XWert, DX, DY, 0, 0, Display.replace);
  549.         END;
  550.         XWert:=f.X+SeitenOffset+XWert;
  551.         YWert:=f.Y+f.H-ObenOffset-f.d.YAuf*Dum;
  552.         FOR DX:=0 TO f.d.XAuf-1 DO
  553.             FOR DY:=0 TO f.d.YAuf-1 DO
  554.                 Display.ReplConstC(f, f.d.Feld[DX, DY], XWert+DX*Dum, YWert+DY*Dum, f.KG, f.KG, Display.replace);
  555.             END;
  556.         END;
  557.     END PlotFeld;
  558.     (* plot one pixel to frame *)
  559.     PROCEDURE PlotKasten(f: Frame; X, Y: INTEGER);
  560.         VAR XPos, YPos: INTEGER;
  561.     BEGIN
  562.         KastenToFrame(f, X, Y, XPos, YPos);
  563.         Oberon.RemoveMarks(XPos, YPos, f.KG, f.KG);
  564.         Display.ReplConstC(f, f.d.Feld[X, Y], XPos, YPos, f.KG, f.KG, Display.replace);
  565.     END PlotKasten;
  566.     (* plot Mode *)
  567.     PROCEDURE PlotMode(f: Frame);
  568.     BEGIN
  569.         Display.ReplConstC(f, Display.black, f.X+SO, f.Y+f.H-OO+1, f.X+SO+49, f.Y+f.H, Display.replace);
  570.         IF f.d.DrawMode=DrawMode THEN
  571.             Texts.WriteString(W, "DRAW");
  572.         ELSIF f.d.DrawMode=FillMode THEN
  573.             Texts.WriteString(W, "FILL");
  574.         ELSIF f.d.DrawMode=InsertMode THEN
  575.             Texts.WriteString(W, "INSERT");
  576.         END;
  577.         DisplayPat.PlotText(f, Display.white, F, W.buf, f.X+SO, f.Y+f.H-17, Display.paint);
  578.     END PlotMode;
  579.     (* plot all new *)
  580.     PROCEDURE PlotAll(f: Frame);
  581.     BEGIN
  582.         Oberon.RemoveMarks(f.X, f.Y, f.W, f.H);
  583.         Display.ReplConst(Display.black, f.X, f.Y, f.W, f.H, Display.replace);
  584.         IF f.d.ActivPat#NIL THEN
  585.             Texts.WriteString(W, "Pattern Number: ");
  586.             Texts.WriteInt(W, GetNumber(f.d.ActivPat), 1);
  587.             Texts.Write(W, "/");
  588.             Texts.WriteInt(W, CountPat(FirstPat(f.d.ActivPat)), 1);
  589.             Texts.WriteString(W, "   Height: ");
  590.             Texts.WriteInt(W, f.d.XAuf, 1);
  591.             Texts.WriteString(W, "   Width: ");
  592.             Texts.WriteInt(W, f.d.YAuf, 1);
  593.             Texts.WriteString(W, "   Zoom: ");
  594.             Texts.WriteInt(W, f.KG, 1);
  595.             DisplayPat.PlotText(f, Display.white, F, W.buf, f.X+SO+60, f.Y+f.H-17, Display.paint);
  596.             PlotMode(f);
  597.             PlotFeld(f);
  598.         END;
  599.     END PlotAll;
  600.     (* clear current pattern *)
  601.     PROCEDURE Clear*;
  602.         VAR
  603.             pamsg: PlotAllMsg;
  604.             f, g: Display.Frame;
  605.             S: Texts.Scanner;
  606.     BEGIN
  607.         IF GetFrame(g) THEN
  608.             f:=g;
  609.             WITH f: Frame DO
  610.                 IF GetPar(S) & (f.d.Feld#NIL) THEN
  611.                     IF S.class=Texts.Int THEN
  612.                         IF (S.i<0) OR (S.i>255) THEN RETURN;END;
  613.                         ClearFeld(f.d, SHORT(S.i));
  614.                     ELSE
  615.                         ClearFeld(f.d, Display.black);
  616.                     END;
  617.                     pamsg.d:=f.d;
  618.                     Viewers.Broadcast(pamsg);
  619.                     MarkData(f);
  620.                 END;
  621.             ELSE
  622.             END;
  623.         END;
  624.     END Clear;
  625.     (* plot one pixel, specified by coordinates *)
  626.     PROCEDURE Plot*;
  627.         VAR
  628.             pkmsg: PlotKastenMsg;
  629.             f, g: Display.Frame;
  630.             X, Y, Color: INTEGER;
  631.             S: Texts.Scanner;
  632.     BEGIN
  633.         IF GetFrame(g) THEN
  634.             f:=g;
  635.             WITH f: Frame DO
  636.                 IF GetPar(S) & (f.d.Feld#NIL) THEN
  637.                     IF S.class=Texts.Int THEN
  638.                         X:=SHORT(S.i);
  639.                         Texts.Scan(S);
  640.                         IF S.class=Texts.Int THEN
  641.                             Y:=SHORT(S.i);
  642.                             IF (X>=0) & (Y>=0) & (X<f.d.XAuf) & (Y<f.d.YAuf) THEN
  643.                                 Texts.Scan(S);
  644.                                 IF S.class=Texts.Int THEN
  645.                                     IF (S.i<0) OR (S.i>=MaxColors) THEN RETURN;END;
  646.                                     Color:=SHORT(S.i);
  647.                                 ELSE
  648.                                     Color:=f.d.Color;
  649.                                 END;
  650.                                 f.d.Feld[X ,Y]:=Color;
  651.                                 pkmsg.X:=X;pkmsg.Y:=Y;
  652.                                 pkmsg.d:=f.d;
  653.                                 Viewers.Broadcast(pkmsg);
  654.                             END;
  655.                         END;
  656.                     END;
  657.                 END;
  658.             ELSE
  659.             END;
  660.         END;
  661.     END Plot;
  662.     (* insert new pattern *)
  663.     PROCEDURE New*;
  664.         VAR
  665.             pamsg: PlotAllMsg;
  666.             f, g: Display.Frame;
  667.             X, Y: INTEGER;
  668.             S: Texts.Scanner;
  669.     BEGIN
  670.         IF GetFrame(g) THEN
  671.             f:=g;
  672.             WITH f: Frame DO
  673.                 IF GetPar(S) THEN
  674.                     IF S.class=Texts.Int THEN
  675.                         X:=SHORT(S.i);
  676.                         Texts.Scan(S);
  677.                         IF S.class=Texts.Int THEN
  678.                             Y:=SHORT(S.i);
  679.                             IF (X>=0) & (Y>=0) & (X<MaxAuf) & (Y<MaxAuf) THEN
  680.                                 StoreToMem(f.d);
  681.                                 NewPat(f.d, X, Y);
  682.                                 f.d.XAuf:=X;f.d.YAuf:=Y;
  683.                                 f.d.Feld:=NIL;
  684.                                 NEW(f.d.Feld, X, Y);
  685.                                 ClearFeld(f.d, Display.black);
  686.                                 pamsg.d:=f.d;
  687.                                 Viewers.Broadcast(pamsg);
  688.                                 MarkData(f);
  689.                             END;
  690.                         END;
  691.                     END;
  692.                 END;
  693.             ELSE
  694.             END;
  695.         END;
  696.     END New;
  697.     (* delete activ pattern *)
  698.     PROCEDURE Delete*;
  699.         VAR
  700.             pamsg: PlotAllMsg;
  701.             f, g: Display.Frame;
  702.     BEGIN
  703.         IF GetFrame(g) THEN
  704.             f:=g;
  705.             WITH f: Frame DO
  706.                 IF f.d.ActivPat#NIL THEN
  707.                     f.d.LastKilled:=f.d.ActivPat;
  708.                     IF f.d.ActivPat.Next=NIL THEN
  709.                         IF f.d.ActivPat.Last=NIL THEN
  710.                             f.d.ActivPat:=NIL;
  711.                         ELSE
  712.                             f.d.ActivPat:=f.d.ActivPat.Last;
  713.                             f.d.ActivPat.Next:=NIL;
  714.                         END;
  715.                     ELSE
  716.                         f.d.ActivPat:=f.d.ActivPat.Next;
  717.                         IF f.d.LastKilled.Last=NIL THEN
  718.                             f.d.ActivPat.Last:=NIL;
  719.                         ELSE
  720.                             f.d.ActivPat.Last:=f.d.LastKilled.Last;
  721.                             f.d.LastKilled.Last.Next:=f.d.ActivPat;
  722.                         END;
  723.                     END;
  724.                     f.d.LastKilled.Next:=NIL;
  725.                     f.d.LastKilled.Last:=NIL;
  726.                     pamsg.d:=f.d;
  727.                     PatToFeld(f.d);
  728.                     Viewers.Broadcast(pamsg);
  729.                     MarkData(f);
  730.                 END;
  731.             ELSE
  732.             END;
  733.         END;
  734.     END Delete;
  735.     (* replot patterns from memory *)
  736.     PROCEDURE Recall*;
  737.         VAR
  738.             f, g: Display.Frame;
  739.             pamsg: PlotAllMsg;
  740.     BEGIN
  741.         IF GetFrame(g) THEN
  742.             f:=g;
  743.             WITH f: Frame DO
  744.                 IF f.d.LastKilled#NIL THEN
  745.                     IF f.d.ActivPat#NIL THEN
  746.                         IF f.d.ActivPat.Next#NIL THEN
  747.                             f.d.ActivPat.Next.Last:=f.d.LastKilled;
  748.                         END;
  749.                         f.d.LastKilled.Next:=f.d.ActivPat.Next;
  750.                         f.d.LastKilled.Last:=f.d.ActivPat;
  751.                         f.d.ActivPat.Next:=f.d.LastKilled;
  752.                     END;
  753.                     f.d.ActivPat:=f.d.LastKilled;
  754.                     PatToFeld(f.d);
  755.                     pamsg.d:=f.d;
  756.                     Viewers.Broadcast(pamsg);
  757.                     f.d.LastKilled:=NIL;
  758.                     MarkData(f);
  759.                 END;
  760.             ELSE
  761.             END;
  762.         END;
  763.     END Recall;
  764.     (* replot patterns from memory *)
  765.     PROCEDURE Undo*;
  766.         VAR
  767.             f, g: Display.Frame;
  768.             pamsg: PlotAllMsg;
  769.     BEGIN
  770.         IF GetFrame(g) THEN
  771.             f:=g;
  772.             WITH f: Frame DO
  773.                 IF (f.d.ActivPat#NIL) & f.d.Marked THEN
  774.                     PatToFeld(f.d);
  775.                     pamsg.d:=f.d;
  776.                     Viewers.Broadcast(pamsg);
  777.                     MarkData(f);
  778.                 END;
  779.             ELSE
  780.             END;
  781.         END;
  782.     END Undo;
  783.     (* duplicate activ pattern *)
  784.     PROCEDURE Duplicate*;
  785.         VAR
  786.             f, g: Display.Frame;
  787.             pamsg: PlotAllMsg;
  788.     BEGIN
  789.         IF GetFrame(g) THEN
  790.             f:=g;
  791.             WITH f: Frame DO
  792.                 IF f.d.ActivPat#NIL THEN
  793.                     StoreToMem(f.d);
  794.                     NewPat(f.d, f.d.ActivPat.W, f.d.ActivPat.H);
  795.                     StoreToMem(f.d);
  796.                     pamsg.d:=f.d;
  797.                     Viewers.Broadcast(pamsg);
  798.                     MarkData(f);
  799.                 END;
  800.             ELSE
  801.             END;
  802.         END;
  803.     END Duplicate;
  804.     (* switch grid on/off *)
  805.     PROCEDURE Grid*;
  806.         VAR
  807.             f, g: Display.Frame;
  808.             pamsg: PlotAllMsg;
  809.     BEGIN
  810.         IF GetFrame(g) THEN
  811.             f:=g;
  812.             WITH f: Frame DO
  813.                 f.Grid:=~f.Grid;
  814.                 pamsg.d:=f.d;
  815.                 f.handle(f, pamsg);
  816.             ELSE
  817.             END;
  818.         END;
  819.     END Grid;
  820.     (* switch grid mode *)
  821.     PROCEDURE GridMode*;
  822.         VAR
  823.             f, g: Display.Frame;
  824.             pamsg: PlotAllMsg;
  825.     BEGIN
  826.         IF GetFrame(g) THEN
  827.             f:=g;
  828.             WITH f: Frame DO
  829.                 f.GridType:=~f.GridType;
  830.                 pamsg.d:=f.d;
  831.                 f.handle(f, pamsg);
  832.             ELSE
  833.             END;
  834.         END;
  835.     END GridMode;
  836.     (* copy frame *)
  837.     PROCEDURE CopyMe(f: Frame): Frame;
  838.         VAR nf: Frame;
  839.     BEGIN
  840.         NEW(nf);IF nf=NIL THEN RETURN NIL;END;
  841.         nf.handle:=f.handle;
  842.         nf.d:=f.d;nf.KG:=f.KG;
  843.         nf.Grid:=f.Grid;nf.GridType:=f.GridType;
  844.         nf.LastModMsg:=TRUE;
  845.         RETURN nf;
  846.     END CopyMe;
  847.     (* store all data to file *)
  848.     PROCEDURE StorePat(d: Data; Name: ARRAY OF CHAR): LONGINT;
  849.         VAR
  850.             File: Files.File;
  851.             Rider: Files.Rider;
  852.             PatDum: Pat;
  853.             PatDataDum: PatData;
  854.             PatAnz, BytesAnz: LONGINT;
  855.             XCount: INTEGER;
  856.     BEGIN
  857.         BytesAnz:=0;
  858.         File:=Files.New(Name);
  859.         Files.Set(Rider, File, 0);
  860.         Files.WriteLInt(Rider, 26021970);
  861.         PatDum:=FirstPat(d.ActivPat);
  862.         PatAnz:=CountPat(PatDum);
  863.         Files.WriteLInt(Rider, PatAnz);
  864.         WHILE PatAnz#0 DO
  865.             Files.WriteInt(Rider, PatDum.W);Files.WriteInt(Rider, PatDum.H);
  866.             PatDataDum:=PatDum;
  867.             WHILE PatDataDum.NextData#NIL DO
  868.                 INC(BytesAnz, 1);
  869.                 PatDataDum:=PatDataDum.NextData;
  870.                 Files.WriteInt(Rider, PatDataDum.Color);
  871.                 FOR XCount:=0 TO PatDum.H-1 DO
  872.                     DisplayPat.WriteSet(Rider, PatDataDum.SetData[XCount]);
  873.                 END;
  874.             END;
  875.             Files.WriteInt(Rider, -1);
  876.             DEC(PatAnz);
  877.             PatDum:=PatDum.Next;
  878.         END;
  879.         Files.Register(File);
  880.         RETURN BytesAnz;
  881.     END StorePat;
  882.     (* load data from file *)
  883.     PROCEDURE LoadPat(d: Data);
  884.         VAR
  885.             File: Files.File;
  886.             Rider: Files.Rider;
  887.             LDum, PatAnz: LONGINT;
  888.             DataDum, LastData: PatData;
  889.             W, H, Color, Count: INTEGER;
  890.     BEGIN
  891.         File:=Files.Old(d.Name);
  892.         IF File=NIL THEN RETURN;END;
  893.         Files.Set(Rider, File, 0);
  894.         Files.ReadLInt(Rider, LDum);
  895.         IF LDum#26021970 THEN RETURN;END;
  896.         Files.ReadLInt(Rider, PatAnz);
  897.         WHILE PatAnz#0 DO
  898.             Files.ReadInt(Rider, W);Files.ReadInt(Rider, H);
  899.             NewPat(d, W, H);LastData:=d.ActivPat;
  900.             Files.ReadInt(Rider, Color);
  901.             WHILE Color#-1 DO
  902.                 NEW(DataDum);DataDum.NextData:=NIL;
  903.                 LastData.NextData:=DataDum;
  904.                 DataDum.Color:=Color;
  905.                 NEW(DataDum.SetData, H);
  906.                 FOR Count:=0 TO H-1 DO
  907.                     DisplayPat.ReadSet(Rider, DataDum.SetData[Count]);
  908.                 END;
  909.                 Files.ReadInt(Rider, Color);
  910.                 LastData:=DataDum;
  911.             END;
  912.             DEC(PatAnz);
  913.         END;
  914.         d.ActivPat:=FirstPat(d.ActivPat);
  915.         PatToFeld(d);
  916.     END LoadPat;
  917.     (* store data to file *)
  918.     PROCEDURE Store*;
  919.         VAR
  920.             S: Texts.Scanner;
  921.             f, g: Display.Frame;
  922.             Name, NameBak: ARRAY 256 OF CHAR;
  923.             Counter: INTEGER;
  924.     BEGIN
  925.         IF GetFrame(g) THEN
  926.             f:=g;
  927.             WITH f: Frame DO
  928.                 COPY(f.d.Name, Name);
  929.                 IF GetPar(S) THEN
  930.                     IF S.class=Texts.Name THEN
  931.                         COPY(S.s, Name);
  932.                     ELSE
  933.                         Texts.OpenScanner(S, f.d.MText, 0);
  934.                         Texts.Scan(S);
  935.                         IF S.class=Texts.Name THEN
  936.                             COPY(S.s, Name);
  937.                         END;
  938.                     END;
  939.                     Texts.WriteString(W, "EditPat.Store ");
  940.                     Texts.WriteString(W, Name);
  941.                     Texts.Write(W, " ");
  942.                     Texts.Append(Oberon.Log, W.buf);
  943.                     COPY(Name, NameBak);
  944.                     Counter:=0;
  945.                     WHILE NameBak[Counter]#0X DO INC(Counter);END;
  946.                     NameBak[Counter]:=".";NameBak[Counter+1]:="B";NameBak[Counter+2]:="a";
  947.                     NameBak[Counter+3]:="k";NameBak[Counter+4]:=0X;
  948.                     Files.Delete(NameBak, Counter);
  949.                     Files.Rename(Name, NameBak, Counter);
  950.                     StoreToMem(f.d);
  951.                     Texts.WriteInt(W, StorePat(f.d, Name), 1);
  952.                     Texts.WriteLn(W);
  953.                     Texts.Append(Oberon.Log, W.buf);
  954.                     IF f.d.Marked THEN
  955.                         f.d.Marked:=FALSE;
  956.                         Texts.Delete(f.d.MText, f.d.MText.len-1, f.d.MText.len);
  957.                     END;
  958.                 END;
  959.             ELSE
  960.             END;
  961.         END;
  962.     END Store;
  963.     (* handel drawing mousaction *)
  964.     PROCEDURE DoDraw(f: Frame; X, Y: INTEGER; k:SET);
  965.         VAR
  966.             LastXKast, LastYKast, XKas, YKas: INTEGER;
  967.             pkmsg: PlotKastenMsg;
  968.             NewKeys: SET;
  969.     BEGIN
  970.         LastXKast:=-1;LastYKast:=-1;
  971.         REPEAT
  972.             Oberon.DrawCursor(Oberon.Mouse, Oberon.Arrow, X, Y);
  973.             IF FrameToKasten(f, X, Y, XKas, YKas) THEN
  974.                 pkmsg.d:=f.d;
  975.                 IF (LastXKast#XKas) OR (LastYKast#YKas) THEN
  976.                     pkmsg.X:=XKas;pkmsg.Y:=YKas;
  977.                     LastXKast:=XKas;LastYKast:=YKas;
  978.                     IF k={2} THEN
  979.                         f.d.Feld[XKas, YKas]:=f.d.Color;
  980.                     ELSE
  981.                         f.d.Feld[XKas, YKas]:=Display.black;
  982.                     END;
  983.                     Viewers.Broadcast(pkmsg);
  984.                     MarkData(f);
  985.                 END;
  986.             END;
  987.             Input.Mouse(NewKeys, X, Y)
  988.         UNTIL (NewKeys#k);
  989.     END DoDraw;
  990.     (* do filling *)
  991.     PROCEDURE FillProc(d: Data; XKas, YKas, Color, OldColor: INTEGER);
  992.         VAR pkmsg: PlotKastenMsg;
  993.     BEGIN
  994.         IF (XKas>=0) & (YKas>=0) & (XKas<d.XAuf) & (YKas<d.YAuf) THEN
  995.             IF d.Feld[XKas, YKas]=OldColor THEN
  996.                 d.Feld[XKas, YKas]:=Color;
  997.                 pkmsg.d:=d;
  998.                 pkmsg.X:=XKas;pkmsg.Y:=YKas;
  999.                 Viewers.Broadcast(pkmsg);
  1000.                 FillProc(d, XKas+1, YKas, Color, OldColor);
  1001.                 FillProc(d, XKas-1, YKas, Color, OldColor);
  1002.                 FillProc(d, XKas, YKas+1, Color, OldColor);
  1003.                 FillProc(d, XKas, YKas-1, Color, OldColor);
  1004.             END;
  1005.         END;
  1006.     END FillProc;
  1007.     (* handel drawing mousaction *)
  1008.     PROCEDURE DoFill(f: Frame; X, Y: INTEGER; k:SET);
  1009.         VAR
  1010.             Color, XKas, YKas: INTEGER;
  1011.             NewKeys: SET;
  1012.     BEGIN
  1013.         IF k={2} THEN
  1014.             Color:=f.d.Color;
  1015.         ELSE
  1016.             Color:=Display.black;
  1017.         END;
  1018.         REPEAT
  1019.             Oberon.DrawCursor(Oberon.Mouse, Oberon.Arrow, X, Y);
  1020.             Input.Mouse(NewKeys, X, Y);
  1021.             k:=k+NewKeys;
  1022.         UNTIL (NewKeys={});
  1023.         IF (k={0}) OR (k={2}) THEN    
  1024.             IF FrameToKasten(f, X, Y, XKas, YKas) THEN
  1025.                 IF Color#f.d.Feld[XKas, YKas] THEN
  1026.                     FillProc(f.d, XKas, YKas, Color, f.d.Feld[XKas, YKas]);
  1027.                     MarkData(f);
  1028.                 END;
  1029.             END;
  1030.         END;
  1031.     END DoFill;
  1032.     (* invert rectangle area for copy and cut *)
  1033.     PROCEDURE InvertRec(f:Frame; X1, Y1, X2, Y2: INTEGER);
  1034.         VAR W, H, Dummy: INTEGER;
  1035.     BEGIN
  1036.         IF X1>X2 THEN
  1037.             Dummy:=X1;
  1038.             X1:=X2;X2:=Dummy;
  1039.         END;
  1040.         IF Y1>Y2 THEN
  1041.             Dummy:=Y1;
  1042.             Y1:=Y2;Y2:=Dummy;
  1043.         END;
  1044.         W:=X2-X1;H:=Y2-Y1;
  1045.         Oberon.RemoveMarks(X1, Y1, W, H);        
  1046.         Display.ReplConstC(f, Display.white, X1, Y1, W, 1, Display.invert);
  1047.         Display.ReplConstC(f, Display.white, X1, Y1, 1, H, Display.invert);
  1048.         Display.ReplConstC(f, Display.white, X1, Y1+H, W, 1, Display.invert);
  1049.         Display.ReplConstC(f, Display.white, X1+W, Y1, 1, H, Display.invert);
  1050.     END InvertRec;
  1051.     (* do copy and cut *)
  1052.     PROCEDURE GetPart(f: Frame; XStart, YStart: INTEGER; k:SET);
  1053.         VAR
  1054.             Color, X, Y, XKasStart, YKasStart, XKasEnd, YKasEnd, XAlt, YAlt: INTEGER;
  1055.             NewKey: SET;
  1056.             pkmsg: PlotKastenMsg;
  1057.     BEGIN
  1058.         IF FrameToKasten(f, XStart, YStart, XKasStart, YKasStart) THEN
  1059.             XAlt:=XStart;YAlt:=YStart;
  1060.             InvertRec(f, XStart, YStart, XStart, YStart);
  1061.             Oberon.DrawCursor(Oberon.Mouse, Oberon.Arrow, XStart, YStart);
  1062.             REPEAT
  1063.                 Input.Mouse(NewKey, X, Y);
  1064.                 k:=k+NewKey;
  1065.                 IF (XAlt#X) OR (YAlt#Y) THEN
  1066.                     InvertRec(f, XAlt, YAlt, XStart, YStart);
  1067.                     XAlt:=X;YAlt:=Y;
  1068.                     InvertRec(f, X, Y, XStart, YStart);
  1069.                     Oberon.DrawCursor(Oberon.Mouse, Oberon.Arrow, X, Y);
  1070.                 END;
  1071.             UNTIL NewKey={};
  1072.             InvertRec(f, X, Y, XStart, YStart);
  1073.             IF FrameToKasten(f, X, Y, XKasEnd, YKasEnd) THEN
  1074.                 IF (k={1}) OR (k={1,0}) OR (k={1,2}) THEN
  1075.                     Color:=-1;pkmsg.d:=f.d;
  1076.                     IF k={1,2} THEN
  1077.                         Color:=f.d.Color;
  1078.                     ELSIF k={0,1} THEN
  1079.                         Color:=Display.black;
  1080.                     END;
  1081.                     IF XKasStart>XKasEnd THEN
  1082.                         X:=XKasStart;
  1083.                         XKasStart:=XKasEnd;XKasEnd:=X;
  1084.                     END;
  1085.                     IF YKasStart>YKasEnd THEN
  1086.                         Y:=YKasStart;
  1087.                         YKasStart:=YKasEnd;YKasEnd:=Y;
  1088.                     END;
  1089.                     ClipW:=XKasEnd-XKasStart+1;
  1090.                     ClipH:=YKasEnd-YKasStart+1;
  1091.                     NEW(Clip, ClipW, ClipH);
  1092.                     FOR X:=0 TO ClipW-1 DO
  1093.                         FOR Y:=0 TO ClipH-1 DO
  1094.                             Clip[X, Y]:=f.d.Feld[XKasStart+X, YKasStart+Y];
  1095.                             IF Color#-1 THEN
  1096.                                 f.d.Feld[XKasStart+X, YKasStart+Y]:=Color;
  1097.                                 pkmsg.X:=XKasStart+X;pkmsg.Y:=YKasStart+Y;
  1098.                                 Viewers.Broadcast(pkmsg);
  1099.                             END;
  1100.                         END;
  1101.                     END;
  1102.                     IF Color#-1 THEN MarkData(f);END;
  1103.                 END;
  1104.             END;
  1105.         END;
  1106.     END GetPart;
  1107.     (* insert clipboard *)
  1108.     PROCEDURE DoInsert(f: Frame; X, Y: INTEGER; k:SET);
  1109.         VAR
  1110.             XCount, YCount, XKas, YKas, W, H: INTEGER;
  1111.             pkmsg: PlotKastenMsg;
  1112.             NewKeys: SET;
  1113.     BEGIN
  1114.         IF Clip#NIL THEN
  1115.             REPEAT
  1116.                 Oberon.DrawCursor(Oberon.Mouse, Oberon.Arrow, X, Y);
  1117.                 Input.Mouse(NewKeys, X, Y);
  1118.                 k:=k+NewKeys;
  1119.             UNTIL (NewKeys#k);
  1120.             IF ((k={0}) OR (k={2})) & FrameToKasten(f, X, Y, XKas, YKas) THEN
  1121.                 IF XKas+ClipW>f.d.XAuf THEN
  1122.                     W:=f.d.XAuf-XKas;
  1123.                 ELSE
  1124.                     W:=ClipW;
  1125.                 END;
  1126.                 IF YKas+ClipH>f.d.YAuf THEN
  1127.                     H:=f.d.YAuf-YKas;
  1128.                 ELSE
  1129.                     H:=ClipH;
  1130.                 END;
  1131.                 pkmsg.d:=f.d;
  1132.                 FOR XCount:=0 TO W-1 DO
  1133.                     FOR YCount:=0 TO H-1 DO
  1134.                         IF (k={2}) OR ~(Clip[XCount, YCount]=Display.black) THEN
  1135.                             f.d.Feld[XCount+XKas, YCount+YKas]:=Clip[XCount, YCount];;
  1136.                             pkmsg.X:=XCount+XKas;pkmsg.Y:=YCount+YKas;
  1137.                             Viewers.Broadcast(pkmsg);
  1138.                         END;
  1139.                     END;
  1140.                 END;
  1141.                 MarkData(f);
  1142.             END;
  1143.         END;
  1144.     END DoInsert;
  1145.     (* do mouseaction *)
  1146.     PROCEDURE TrackMouse(f: Frame; X, Y: INTEGER; k: SET);
  1147.         VAR
  1148.             XPos, YPos: INTEGER;
  1149.             NewKeys, FirstKey: SET;
  1150.             XKas, YKas: INTEGER;
  1151.     BEGIN
  1152.         IF f.d.ActivPat#NIL THEN
  1153.             IF k={1} THEN
  1154.                 GetPart(f, X, Y, k);
  1155.             ELSIF f.d.DrawMode=DrawMode THEN
  1156.                 IF (k={0}) OR (k={2}) THEN DoDraw(f, X, Y, k);END;
  1157.             ELSIF f.d.DrawMode=FillMode THEN
  1158.                 IF (k={0}) OR (k={2}) THEN DoFill(f, X, Y, k);END;
  1159.             ELSIF f.d.DrawMode=InsertMode THEN
  1160.                 IF (k={0}) OR (k={2}) THEN DoInsert(f, X, Y, k);END;
  1161.             END;
  1162.         END;
  1163.         XPos:=X;YPos:=Y;
  1164.         FirstKey:=k;
  1165.         REPEAT
  1166.             Input.Mouse(NewKeys, X, Y);
  1167.             Oberon.DrawCursor(Oberon.Mouse, Oberon.Arrow, X, Y);
  1168.             k:=k+NewKeys;
  1169.         UNTIL NewKeys={};
  1170.     END TrackMouse;
  1171.     (* the handler of the frame *)
  1172.     PROCEDURE Handler(f: Display.Frame; VAR m: Display.FrameMsg);
  1173.         VAR
  1174.             self: Frame;
  1175.             dumY, dumH: INTEGER;
  1176.     BEGIN
  1177.         self:=f(Frame);
  1178.         WITH m: Oberon.InputMsg DO
  1179.             IF m.id=Oberon.track THEN TrackMouse(self, m.X, m.Y, m.keys);END;
  1180.         | m: Oberon.CopyMsg DO
  1181.             m.F:=CopyMe(self);
  1182.         | m: MenuViewers.ModifyMsg DO
  1183.             IF m.H=0 THEN
  1184.                 self.LastModMsg:=TRUE;
  1185.                 RETURN;
  1186.             END;
  1187.             IF m.id=MenuViewers.extend THEN    (* extended *)
  1188.                 f.Y:=m.Y;f.H:=m.H;
  1189.                 PlotAll(self);
  1190.             ELSIF m.id=MenuViewers.reduce THEN    (* reduced *)
  1191.                 dumY:=f.Y;dumH:=f.H;
  1192.                 f.Y:=m.Y;f.H:=m.H;
  1193.                 IF m.dY#0 THEN             (* if top moved, copy *)
  1194.                     Oberon.RemoveMarks(self.X, m.Y, self.W, m.H-m.dY);
  1195.                     Display.CopyBlock(self.X, dumY+dumH-m.H, self.W, m.H, self.X, m.Y, Display.replace);
  1196.                 END;
  1197.             END;
  1198.             self.LastModMsg:=FALSE;
  1199.         | m: EditPatMsg DO
  1200.             IF (self.d=m.d) OR (m.d=NIL) THEN
  1201.                 WITH m: PlotAllMsg DO
  1202.                     PlotAll(self);
  1203.                 | m: PlotKastenMsg DO
  1204.                     PlotKasten(self, m.X, m.Y);
  1205.                 | m: DrawModeMsg DO
  1206.                     PlotMode(self);
  1207.                 ELSE
  1208.                 END;
  1209.             END;
  1210.         ELSE
  1211.         END;
  1212.     END Handler;
  1213.     (* open new edit frame *)
  1214.     PROCEDURE CopyFrame*;
  1215.         VAR
  1216.             x, y: INTEGER;
  1217.             g, h: Display.Frame;
  1218.             f: Frame;
  1219.             tf: TextFrames.Frame;
  1220.             v: MenuViewers.Viewer;
  1221.     BEGIN
  1222.         IF GetFrame(g) THEN
  1223.             h:=g;
  1224.             WITH h: Frame DO
  1225.                 NEW(f);IF f=NIL THEN RETURN;END;
  1226.                 f.Grid:=FALSE;f.GridType:=TRUE;
  1227.                 f.KG:=1;f.d:=h.d;
  1228.                 f.handle:=Handler;
  1229.                 f.LastModMsg:=TRUE;
  1230.                 Oberon.AllocateUserViewer(Oberon.Mouse.X, x, y);
  1231.                 tf:=TextFrames.NewMenu("", "");
  1232.                 tf.text:=f.d.MText;
  1233.                 v:=MenuViewers.New(tf, f, TextFrames.menuH, x, y);
  1234.             ELSE
  1235.             END;
  1236.         END;
  1237.     END CopyFrame;
  1238.     PROCEDURE MenuFrame(name: ARRAY OF CHAR): TextFrames.Frame;
  1239.         VAR
  1240.             mf: TextFrames.Frame;
  1241.             buf: Texts.Buffer;
  1242.             t: Texts.Text;
  1243.             r: Texts.Reader;
  1244.             end: LONGINT;
  1245.             ch: CHAR;
  1246.     BEGIN
  1247.         IF Files.Old("EditPat.Menu.Text")=NIL THEN
  1248.             mf:=TextFrames.NewMenu(name, Menu);
  1249.         ELSE
  1250.             mf:=TextFrames.NewMenu(name, "");
  1251.             NEW(t);Texts.Open(t, "EditPat.Menu.Text");
  1252.             Texts.OpenReader(r, t, 0);
  1253.             REPEAT
  1254.                 Texts.Read(r, ch);
  1255.             UNTIL r.eot OR (ch=0DX);
  1256.             IF r.eot THEN
  1257.                 end:=t.len;
  1258.             ELSE
  1259.                 end:=Texts.Pos(r)-1;
  1260.             END;
  1261.             NEW(buf); Texts.OpenBuf(buf);
  1262.             Texts.Save(t, 0, end, buf);Texts.Append(mf.text, buf)
  1263.         END;
  1264.         RETURN mf;
  1265.     END MenuFrame;
  1266.     (* open new edit frame *)
  1267.     PROCEDURE Open*;
  1268.         VAR
  1269.             x, y: INTEGER;
  1270.             f: Frame;
  1271.             d: Data;
  1272.             v: MenuViewers.Viewer;
  1273.             S: Texts.Scanner;
  1274.     BEGIN
  1275.         NEW(f);IF f=NIL THEN RETURN;END;
  1276.         NEW(d);f.d:=d;
  1277.         f.Grid:=TRUE;f.GridType:=TRUE;
  1278.         d.ActivPat:=NIL;d.LastKilled:=NIL;d.Feld:=NIL;
  1279.         f.KG:=20;f.d.Marked:=FALSE;
  1280.         d.Color:=Display.white;
  1281.         f.handle:=Handler;
  1282.         d.Name:="Empty.Pat";
  1283.         IF GetPar(S) THEN
  1284.             IF S.class=Texts.Name THEN
  1285.                 COPY(S.s, d.Name);
  1286.                 LoadPat(d);
  1287.             END;
  1288.         END;
  1289.         f.LastModMsg:=TRUE;
  1290.         d.DrawMode:=DrawMode;
  1291.         Oberon.AllocateUserViewer(Oberon.Mouse.X, x, y);
  1292.         v:=MenuViewers.New(MenuFrame(f.d.Name), f, TextFrames.menuH, x, y);
  1293.         f.d.MText:=v.dsc(TextFrames.Frame).text;
  1294.     END Open;
  1295. BEGIN
  1296.     Clip:=NIL;
  1297.     F:=Fonts.This("Syntax12.Scn.Fnt");
  1298.     Texts.OpenWriter(W);
  1299.     Texts.WriteString(W, "EditPat V0.6");
  1300.     Texts.WriteLn(W);
  1301.     Texts.WriteString(W, "(C) 4 Nov 94 by Ralf Degner");
  1302.     Texts.WriteLn(W);
  1303.     Texts.Append(Oberon.Log, W.buf);
  1304. END EditPat.
  1305.